#include "file_utils.h"

#include <cctype>
#include <vector>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

#include "dfs_error.h"
#include "dfs_types.h"

namespace HarmonyOS {
namespace DistributedFs {
constexpr uint64_t MONTH_SHIFT = 8;
constexpr uint64_t MILLISECONDS_FACTOR = 10;
constexpr uint64_t SECOND_SHIFT = 8;
constexpr uint64_t HOUR_SHIFT = 8;
constexpr uint64_t HIYEAR_SHIFT = 16;

uint32_t FileUtils::Stat(const std::string &path, struct stat &s)
{
    if (path.empty()) {
        return ERR_INVAL;
    }

    if (stat(path.c_str(), &s) != 0) {
        return DfsErrors::ConvertErrno(errno);
    }

    return SUCCESS;
}

uint32_t FileUtils::Stat(int fd, struct stat &s)
{
    if (fd < 0) {
        return ERR_INVAL;
    }

    if (fstat(fd, &s) != 0) {
        return DfsErrors::ConvertErrno(errno);
    }

    return SUCCESS;
}

uint32_t FileUtils::TruncateFile(int fd, uint64_t size)
{
    if (fd < 0) {
        return ERR_INVAL;
    }

    int ret = ftruncate(fd, size);
    if (ret < 0) {
        return DfsErrors::ConvertErrno(errno);
    }

    return SUCCESS;
}

ssize_t FileUtils::ReadFile(int fd, off_t offset, size_t size, void *data)
{
    if ((fd < 0) || (offset < 0) || (size < 0) || (data == nullptr)) {
        return -1;
    }

    size_t readLen = 0;
    lseek(fd, offset, 0);
    while (readLen < size) {
        ssize_t ret = read(fd, data, size - readLen);
        if (ret < 0) {
            return ret;
        } else if (ret == 0) {
            break;
        }
        readLen += ret;
    }

    return readLen;
}

ssize_t FileUtils::WriteFile(int fd, const void *data, off_t offset, size_t size)
{
    if ((fd < 0) || (offset < 0) || (size < 0) || (data == nullptr)) {
        return -1;
    }

    size_t writeLen = 0;
    lseek(fd, offset, 0);
    while (writeLen < size) {
        ssize_t ret = write(fd, data, size - writeLen);
        if ((ret < 0) || (ret == 0)) {
            return ret;
        }
        writeLen += ret;
    }

    return writeLen;
}

ssize_t FileUtils::ReadFile(const std::string &path, off_t offset, size_t size, void *data)
{
    return 0;
}

ssize_t FileUtils::WriteFile(const std::string &path, const void *data, off_t offset, size_t size)
{
    return 0;
}

} // namespace DistributedFs
} // namespace HarmonyOS
